import {
  HttpException,
  HttpStatus,
  Injectable,
  Query,
  Req,
} from '@nestjs/common';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';

import { CreateUserDto, LoginUserDto, UserDetailDto } from './dto/user.dto';
import { User } from './entities/user.entity';

import { JwtTool } from '@/utils/tool';
import {
  AdminLoginUserDto,
  AdminUserPageReqDto,
  AdminUserResDto,
} from './dto/admin-user.dto';

@Injectable()
export class UserService {
  private jwt = new JwtTool();

  constructor(
    @InjectRepository(User)
    private readonly usersRepository: Repository<User>,
    // private readonly analyticsService: AnalyticsService,
  ) {}

  async create(user: CreateUserDto) {
    const findUser = await this.usersRepository.findOne({
      where: { phone: user.phone },
    });

    if (findUser) {
      throw new HttpException('该用户已存在', HttpStatus.BAD_REQUEST);
    }

    const newUser = this.usersRepository.create({
      phone: user.phone,
      name: user.name,
      height: user.height,
      weight: user.weight,
      birthDate: user.birthDate,
      education: user.education,
      comorbidities: user.comorbidities,
      password: await this.jwt.hashPassword(user.password),
      gender: user.gender,
      platform: 'APP',
      role: user.role,
      // password: user.password,
    });
    await this.usersRepository.save(newUser);
  }

  async login(user: LoginUserDto) {
    const findUser = await this.usersRepository.findOne({
      where: { phone: user.phone, isDeleted: false, platform: 'APP' },
      select: [
        'platform',
        'userId',
        'phone',
        'password',
        'birthDate',
        'createdAt',
        'updatedAt',
        'name',
        'inflammatoryTendency',
        'comorbidities',
        'education',
        'gender',
        'height',
        'weight',
        'role',
        'totalPoint',
        'reminderTimes',
      ],
    });
    if (!findUser) {
      throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
    }
    const isPasswordValid = await this.jwt.validatePassword(
      user.password,
      findUser.password,
    );

    if (!isPasswordValid) {
      throw new HttpException('密码错误', HttpStatus.UNAUTHORIZED);
    }
    const token = this.jwt.generateToken({ ...findUser, password: undefined });

    return { token, user: findUser };
  }

  async adminLogin(data: AdminLoginUserDto) {
    const findUser = await this.usersRepository.findOne({
      where: { phone: data.phone, isDeleted: false, platform: 'ADMIN' },
      select: [
        'platform',
        'userId',
        'phone',
        'password',
        'birthDate',
        'createdAt',
        'updatedAt',
        'name',
        'inflammatoryTendency',
        'comorbidities',
        'education',
        'gender',
        'height',
        'weight',
        'role',
        'totalPoint',
        'reminderTimes',
      ],
    });
    if (!findUser) {
      throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
    }
    const isPasswordValid = await this.jwt.validatePassword(
      data.password,
      findUser.password,
    );

    if (!isPasswordValid) {
      throw new HttpException('密码错误', HttpStatus.UNAUTHORIZED);
    }
    const token = this.jwt.generateToken({ ...findUser, password: undefined });

    return token;
  }

  findAll(): Promise<User[]> {
    return this.usersRepository.find();
  }

  async findAllForPage(
    @Query() params: AdminUserPageReqDto,
  ): Promise<AdminUserResDto> {
    const pageNo = params.pageNo || 1;
    const pageSize = params.pageSize || 10;

    const [list, total] = await this.usersRepository.findAndCount({
      where: { isDeleted: false },
      skip: (pageNo - 1) * pageSize,
      take: pageSize,
    });
    return { list, total };
  }

  async findCurUser(user: User): Promise<UserDetailDto | null> {
    const userDetail = await this.usersRepository.findOne({
      where: {
        userId: user.userId,
      },
      select: [
        'userId',
        'phone',
        'birthDate',
        'createdAt',
        'updatedAt',
        'name',
        'inflammatoryTendency',
        'comorbidities',
        'education',
        'gender',
        'height',
        'weight',
        'role',
        'totalPoint',
        'reminderTimes',
      ],
      relations: ['dietLogs', 'messages', 'points'],
    });
    return userDetail;
  }

  async findOne(userId: number): Promise<UserDetailDto | null> {
    const userDetail = await this.usersRepository.findOne({
      where: {
        userId: userId,
      },
      select: [
        'userId',
        'phone',
        'birthDate',
        'createdAt',
        'updatedAt',
        'name',
        'inflammatoryTendency',
        'comorbidities',
        'education',
        'gender',
        'height',
        'weight',
        'role',
        'totalPoint',
        'reminderTimes',
      ],
      relations: ['dietLogs', 'analyticsEvents', 'messages', 'points'],
    });
    return userDetail;
  }

  update(userId: number, params: Partial<CreateUserDto>) {
    return this.usersRepository.save({
      userId,
      ...params,
    });
  }

  count() {
    return this.usersRepository.count({
      where: { isDeleted: false },
    });
  }

  async fakeRemove(userId: number) {
    const findUser = await this.usersRepository.findOne({
      where: { userId, isDeleted: false },
    });
    if (!findUser) {
      throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);
    }
    findUser.isDeleted = true;
    return this.usersRepository.save(findUser);
  }

  findFamily(userId: number) {
    return this.usersRepository.find({
      where: { userId, isDeleted: false },
      relations: ['family'],
    });
  }
}
